

package com.ly.blog_user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.blog_common.constant.Constant;
import com.ly.blog_common.entity.SysUserTokenEntity;
import com.ly.blog_common.security.JwtUserDetails;
import com.ly.blog_common.utils.RequestUtils;
import com.ly.blog_user.dao.SysUserTokenDao;
import com.ly.blog_user.security.SecurityUtils;
import com.ly.blog_user.security.TokenGeneratorUtils;
import com.ly.blog_user.service.SysUserTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("sysUserTokenService")
public class SysUserTokenServiceImpl extends ServiceImpl<SysUserTokenDao, SysUserTokenEntity> implements SysUserTokenService {


	@Autowired
    private RedisTemplate redisTemplate;

    /**
     * 保存token。设定userId ， token中记录userId值。 用于后面校验。当前
     * @param authentication  认证信息
     * @return token值
     */
	@Override
	public String createToken(Authentication authentication) {

	    String token = null;
		//当前时间
		Date now = new Date();
		//过期时间
		Date expireTime = new Date(now.getTime() + Constant.EXPIRE * 1000);

        //生成一个token
        token = TokenGeneratorUtils.generateValue();


        //判断是否生成过token
        JwtUserDetails jwtUserDetails = (JwtUserDetails) authentication.getPrincipal();
        long userId = jwtUserDetails.getUserId();
        SysUserTokenEntity tokenEntity = this.getById(userId);
        if(tokenEntity == null){
            tokenEntity = new SysUserTokenEntity();
            tokenEntity.setUserId(userId);
            tokenEntity.setUserDetail(JSON.toJSONString(jwtUserDetails));
            tokenEntity.setToken(token);
            tokenEntity.setUpdateTime(now);
            tokenEntity.setExpireTime(expireTime);

            //保存token
            this.save(tokenEntity);
        }else{ //用户二次登录 ， 前面登录无效
            tokenEntity.setToken(token);
            tokenEntity.setUserDetail(JSON.toJSONString(jwtUserDetails));
            tokenEntity.setUpdateTime(now);
            tokenEntity.setExpireTime(expireTime);

            //更新token
            this.updateById(tokenEntity);
        }

        //redis 保存token - 采用token记录，反推数据
        redisTemplate.opsForValue().set(String.valueOf(token),tokenEntity,Constant.EXPIRE,TimeUnit.SECONDS);
        log.info("【用户登录记录】 - {}",JSON.toJSONString(jwtUserDetails.getUser()));

		return token;
	}


    @Override
    public SysUserTokenEntity getSysUserTokenEntityFromToken(String token) {
	    // 上下文中Authentication为空 -- 数据库获取
        SysUserTokenEntity sysUserTokenEntity = this.getOne(new QueryWrapper<SysUserTokenEntity>().eq("token", token));
        return sysUserTokenEntity;
    }

    @Override
	public void logout(long userId, HttpServletRequest request) {

        String token = RequestUtils.getToken(request);

        SysUserTokenEntity tokenEntity = (SysUserTokenEntity) redisTemplate.opsForValue().getAndSet(token,null);
        SecurityUtils.setAuthentication(null);

        //修改token
        if(tokenEntity != null) {
            tokenEntity.setUserId(userId);
            tokenEntity.setToken(null);
            tokenEntity.setUpdateTime(new Date());
        }
        this.updateById(tokenEntity);

	}

}
